const express = require('express');
const router = express.Router();
const Progress = require('../models/Progress');
const User = require('../models/User');
const Pattern = require('../models/Pattern');
const Challenge = require('../models/Challenge');
const auth = require('../middleware/auth');
const AIService = require('../services/ai/aiService');

// Initialize AI service
const aiService = new AIService();

/**
 * @route   GET api/progress
 * @desc    Get user's overall progress
 * @access  Private
 */
router.get('/', auth, async (req, res) => {
  try {
    // Get user with populated progress
    const user = await User.findById(req.user.id)
      .select('progress')
      .populate('progress.currentPattern')
      .populate('progress.completedPatterns.beginner')
      .populate('progress.completedPatterns.intermediate')
      .populate('progress.completedPatterns.advanced');
    
    // Get all patterns
    const patterns = await Pattern.find().select('_id name category').sort({ order: 1 });
    
    // Calculate progress statistics
    const totalPatterns = 23; // Total GOF patterns
    const completedBeginner = user.progress.completedPatterns.beginner.length;
    const completedIntermediate = user.progress.completedPatterns.intermediate.length;
    const completedAdvanced = user.progress.completedPatterns.advanced.length;
    
    // Determine if user can level up
    let canLevelUp = false;
    let nextLevel = null;
    
    if (user.progress.currentLevel === 'beginner' && completedBeginner === totalPatterns) {
      canLevelUp = true;
      nextLevel = 'intermediate';
    } else if (user.progress.currentLevel === 'intermediate' && completedIntermediate === totalPatterns) {
      canLevelUp = true;
      nextLevel = 'advanced';
    }
    
    // Check if user has graduated (completed all advanced patterns)
    const hasGraduated = user.progress.currentLevel === 'advanced' && completedAdvanced === totalPatterns;
    
    // Format response
    const progressData = {
      currentLevel: user.progress.currentLevel,
      currentPattern: user.progress.currentPattern,
      completedPatterns: {
        beginner: user.progress.completedPatterns.beginner,
        intermediate: user.progress.completedPatterns.intermediate,
        advanced: user.progress.completedPatterns.advanced
      },
      statistics: {
        beginner: {
          completed: completedBeginner,
          total: totalPatterns,
          percentage: Math.round((completedBeginner / totalPatterns) * 100)
        },
        intermediate: {
          completed: completedIntermediate,
          total: totalPatterns,
          percentage: Math.round((completedIntermediate / totalPatterns) * 100)
        },
        advanced: {
          completed: completedAdvanced,
          total: totalPatterns,
          percentage: Math.round((completedAdvanced / totalPatterns) * 100)
        }
      },
      achievements: user.progress.achievements,
      canLevelUp,
      nextLevel,
      hasGraduated,
      allPatterns: patterns
    };
    
    res.json(progressData);
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

/**
 * @route   GET api/progress/pattern/:patternId
 * @desc    Get user's progress for a specific pattern
 * @access  Private
 */
router.get('/pattern/:patternId', auth, async (req, res) => {
  try {
    // Get user's current level
    const user = await User.findById(req.user.id).select('progress.currentLevel');
    
    // Get progress entries for the pattern at the user's current level
    const progress = await Progress.find({
      user: req.user.id,
      pattern: req.params.patternId,
      level: user.progress.currentLevel
    }).populate({
      path: 'challenge',
      select: 'title description level'
    });
    
    res.json(progress);
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

/**
 * @route   GET api/progress/challenge/:challengeId
 * @desc    Get user's progress for a specific challenge
 * @access  Private
 */
router.get('/challenge/:challengeId', auth, async (req, res) => {
  try {
    const progress = await Progress.findOne({
      user: req.user.id,
      challenge: req.params.challengeId
    });
    
    if (!progress) {
      return res.status(404).json({ msg: 'Progress not found' });
    }
    
    res.json(progress);
  } catch (err) {
    console.error(err.message);
    
    if (err.kind === 'ObjectId') {
      return res.status(404).json({ msg: 'Progress not found' });
    }
    
    res.status(500).send('Server Error');
  }
});

/**
 * @route   PUT api/progress/level-up
 * @desc    Level up user
 * @access  Private
 */
router.put('/level-up', auth, async (req, res) => {
  try {
    // Get user
    const user = await User.findById(req.user.id);
    
    if (!user) {
      return res.status(404).json({ msg: 'User not found' });
    }
    
    // Check current level
    const currentLevel = user.progress.currentLevel;
    let nextLevel = null;
    
    if (currentLevel === 'beginner') {
      nextLevel = 'intermediate';
    } else if (currentLevel === 'intermediate') {
      nextLevel = 'advanced';
    } else {
      return res.status(400).json({ msg: 'Already at maximum level' });
    }
    
    // Update user level
    user.progress.currentLevel = nextLevel;
    user.progress.currentPattern = null;
    await user.save();
    
    // Generate challenges for the new level
    // This is now handled by the frontend, which will call the generate-challenges endpoint
    
    res.json({
      msg: `Successfully upgraded to ${nextLevel} level`,
      level: nextLevel
    });
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

/**
 * @route   PUT api/progress/select-pattern/:patternId
 * @desc    Select a pattern to work on
 * @access  Private
 */
router.put('/select-pattern/:patternId', auth, async (req, res) => {
  try {
    const patternId = req.params.patternId;
    
    // Check if pattern exists
    const pattern = await Pattern.findById(patternId);
    if (!pattern) {
      return res.status(404).json({ msg: 'Pattern not found' });
    }
    
    // Get user
    const user = await User.findById(req.user.id);
    
    // 移除模式锁定检查，允许用户选择任何模式
    // 更新当前模式
    user.progress.currentPattern = patternId;
    await user.save();
    
    res.json({
      msg: `Now working on ${pattern.name} pattern`,
      currentPattern: pattern
    });
  } catch (err) {
    console.error(err.message);
    
    if (err.kind === 'ObjectId') {
      return res.status(404).json({ msg: 'Pattern not found' });
    }
    
    res.status(500).send('Server Error');
  }
});

/**
 * @route   GET api/progress/statistics
 * @desc    Get user's statistics
 * @access  Private
 */
router.get('/statistics', auth, async (req, res) => {
  try {
    // Get all user progress
    const allProgress = await Progress.find({ user: req.user.id });
    
    // Calculate statistics
    const totalChallenges = allProgress.length;
    const completedChallenges = allProgress.filter(p => p.completed).length;
    const totalAttempts = allProgress.reduce((sum, p) => sum + p.attempts, 0);
    
    // Calculate ratings distribution
    const ratings = {
      Unsatisfactory: 0,
      Satisfactory: 0,
      Good: 0,
      Excellent: 0
    };
    
    allProgress.forEach(p => {
      if (p.evaluation && p.evaluation.rating) {
        ratings[p.evaluation.rating]++;
      }
    });
    
    // Calculate time spent
    const totalTimeSpent = allProgress.reduce((sum, p) => sum + (p.timeSpent || 0), 0);
    const avgTimePerChallenge = totalChallenges > 0 ? totalTimeSpent / totalChallenges : 0;
    
    res.json({
      challenges: {
        total: totalChallenges,
        completed: completedChallenges,
        completion: totalChallenges > 0 ? Math.round((completedChallenges / totalChallenges) * 100) : 0
      },
      attempts: {
        total: totalAttempts,
        average: totalChallenges > 0 ? (totalAttempts / totalChallenges).toFixed(1) : 0
      },
      ratings,
      time: {
        total: totalTimeSpent, // in seconds
        average: Math.round(avgTimePerChallenge) // in seconds
      }
    });
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

/**
 * @route   POST api/progress/generate-challenges
 * @desc    Generate challenges for patterns using AI
 * @access  Private
 */
router.post('/generate-challenges', auth, async (req, res) => {
  try {
    const { patternIds, patternType } = req.body;
    
    if (!patternIds || !Array.isArray(patternIds) || !patternType) {
      return res.status(400).json({ msg: 'Pattern IDs and type are required' });
    }
    
    // Get user's current level
    const user = await User.findById(req.user.id);
    const level = user.progress.currentLevel;
    
    if (level === 'beginner') {
      return res.status(400).json({ msg: 'Cannot generate challenges for beginner level' });
    }
    
    const generatedChallenges = [];
    const failedPatterns = [];
    
    // Process patterns in batches to avoid overwhelming the AI service
    for (const patternId of patternIds) {
      try {
        // Get pattern details
        const pattern = await Pattern.findById(patternId);
        
        if (!pattern) {
          failedPatterns.push({ id: patternId, reason: 'Pattern not found' });
          continue;
        }
        
        // Check if challenge already exists for this pattern at this level
        const existingChallenge = await Challenge.findOne({
          pattern: patternId,
          level
        });
        
        if (existingChallenge) {
          // Challenge already exists, no need to generate
          generatedChallenges.push({
            patternId,
            patternName: pattern.name,
            challengeId: existingChallenge._id,
            title: existingChallenge.title,
            status: 'existing'
          });
          continue;
        }
        
        // Generate challenge using AI
        const challengeData = await aiService.generateChallenge(
          pattern.name,
          pattern.category,
          level
        );
        
        // Create new challenge
        const newChallenge = new Challenge({
          title: challengeData.title,
          description: challengeData.description,
          pattern: patternId,
          level,
          scenario: challengeData.scenario,
          requirements: challengeData.requirements,
          hints: challengeData.hints,
          sampleSolution: challengeData.sampleSolution,
          timeLimit: challengeData.timeLimit,
          difficulty: challengeData.difficulty,
          tags: [pattern.name.toLowerCase().replace(' ', '-'), level, pattern.category.toLowerCase()]
        });
        
        await newChallenge.save();
        
        generatedChallenges.push({
          patternId,
          patternName: pattern.name,
          challengeId: newChallenge._id,
          title: newChallenge.title,
          status: 'generated'
        });
      } catch (error) {
        console.error(`Error generating challenge for pattern ${patternId}:`, error);
        failedPatterns.push({ 
          id: patternId, 
          reason: error.message || 'Unknown error'
        });
      }
    }
    
    res.json({
      generated: generatedChallenges,
      failed: failedPatterns,
      level,
      patternType
    });
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

/**
 * @route   PUT api/progress/reset
 * @desc    Reset user's progress (clear completed patterns)
 * @access  Private
 */
router.put('/reset', auth, async (req, res) => {
  try {
    // Get user
    const user = await User.findById(req.user.id);
    
    if (!user) {
      return res.status(404).json({ msg: 'User not found' });
    }
    
    // Reset completed patterns for current level
    user.progress.completedPatterns[user.progress.currentLevel] = [];
    user.progress.currentPattern = null;
    
    await user.save();
    
    // Delete all progress entries for the current level
    await Progress.deleteMany({ 
      user: req.user.id,
      level: user.progress.currentLevel
    });
    
    res.json({
      msg: `Successfully reset progress for ${user.progress.currentLevel} level`,
      level: user.progress.currentLevel
    });
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

/**
 * @route   PUT api/progress/complete-all
 * @desc    Mark all patterns as completed for current level
 * @access  Private
 */
router.put('/complete-all', auth, async (req, res) => {
  try {
    // Get user
    const user = await User.findById(req.user.id);
    
    if (!user) {
      return res.status(404).json({ msg: 'User not found' });
    }
    
    // Get all patterns
    const patterns = await Pattern.find().select('_id');
    const patternIds = patterns.map(p => p._id);
    
    // Set all patterns as completed for current level
    user.progress.completedPatterns[user.progress.currentLevel] = patternIds;
    user.progress.currentPattern = null;
    
    // Determine if user can level up
    let canLevelUp = false;
    let nextLevel = null;
    
    if (user.progress.currentLevel === 'beginner') {
      canLevelUp = true;
      nextLevel = 'intermediate';
    } else if (user.progress.currentLevel === 'intermediate') {
      canLevelUp = true;
      nextLevel = 'advanced';
    }
    
    await user.save();
    
    res.json({
      msg: `Successfully completed all patterns for ${user.progress.currentLevel} level`,
      level: user.progress.currentLevel,
      canLevelUp,
      nextLevel
    });
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

/**
 * @route   PUT api/progress/reset-to-beginner
 * @desc    Reset user's progress to beginner level
 * @access  Private
 */
router.put('/reset-to-beginner', auth, async (req, res) => {
  try {
    // Get user
    const user = await User.findById(req.user.id);
    
    if (!user) {
      return res.status(404).json({ msg: 'User not found' });
    }
    
    // 重置用户进度到初级
    user.progress = {
      currentLevel: 'beginner',
      nextLevel: 'intermediate',
      canLevelUp: false,
      completedPatterns: {
        beginner: [],
        intermediate: [],
        advanced: []
      }
    };
    
    await user.save();
    
    // 删除所有进度记录
    await Progress.deleteMany({ user: req.user.id });
    
    res.json({
      msg: 'Progress reset to beginner level',
      currentLevel: 'beginner'
    });
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

module.exports = router; 